#include "FragmentShader.h"
void FragmentShader::attahProgramObject(GLhandleARB      prog)
{
	if(prog!=0)
		program = prog;

}

bool FragmentShader::loadFragmentShader(const char*fragmentSrc)
{
	 if(fragmentSrc!= 0)
	  {
	  const  char *vsStringPtr[1] ;
	 
	  vsStringPtr[0] = fragmentSrc;
	  fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	  glShaderSourceARB(fragmentShader,1, vsStringPtr,0);
	  glCompileShaderARB(fragmentShader);

	    
	  glGetShaderiv(fragmentShader,GL_COMPILE_STATUS,&shaderCompileStatus);
		
	  if(shaderCompileStatus == GL_FALSE)
	  {   
			loadLog(fragmentShader);
		 
			return false;
	  }
		glAttachShader(program,fragmentShader);
	  }

	

	 return true;
}

void FragmentShader::linkFragmentShader()
{
	 glLinkProgramARB(program);
}

void    FragmentShader :: bind ()
{   
    glUseProgramObjectARB ( program );


}

void    FragmentShader :: unbind ()
{
    glUseProgramObjectARB ( 0 );
}



bool    FragmentShader :: checkGlError ()
{
    bool    retCode = true;
 	GLenum  glErr   = glGetError();

    if ( glErr == GL_NO_ERROR )
    	return retCode;

    glError = (const char *) gluErrorString ( glErr );		

    return false;
}

void    FragmentShader :: clear ()
{
    glDeleteObjectARB ( program        );                   
    glDeleteObjectARB ( fragmentShader   );
   


    program        = 0;
    fragmentShader   = 0;
  
    ok             = false;
}

void    FragmentShader :: loadLog ( GLhandleARB object )
{
    int         logLength     = 0;
    int         charsWritten  = 0;
    GLcharARB   buffer [2048];
    GLcharARB * infoLog;

    glGetObjectParameterivARB ( object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength );

  

    if ( logLength < 1 )
        return;
                                   
    if ( logLength > sizeof ( buffer ) )
    {
        infoLog = (GLcharARB*) malloc ( logLength );

        if ( infoLog == NULL )
        {
            log = "ERROR: Could not allocate log buffer";

            return;
        }
    }
    else
        infoLog = buffer;

    glGetInfoLogARB ( object, logLength, &charsWritten, infoLog );

    log += infoLog;

    if ( infoLog != buffer )
        free ( infoLog );
}

bool    FragmentShader :: setVector ( const char * name, const Vector4D& value )
{
    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return false;

    glUniform4fvARB ( loc, 1, value );

    return true;
}

bool    FragmentShader :: setVector  ( int loc, const Vector4D& value )
{
    glUniform4fvARB ( loc, 1, value );

    return true;
}

bool    FragmentShader :: setVector ( const char * name, const Vector3D& value )
{
    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return false;

    glUniform3fvARB ( loc, 1, value );

    return true;
}

bool    FragmentShader :: setVector  ( int loc, const Vector3D& value )
{
    glUniform3fvARB ( loc, 1, value );

    return true;
}

bool    FragmentShader :: setVector ( const char * name, const Vector2D& value )
{
    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return false;

    glUniform2fvARB ( loc, 1, value );

    return true;
}

bool    FragmentShader :: setVector  ( int loc, const Vector2D& value )
{
    glUniform2fvARB ( loc, 1, value );

    return true;
}

bool    FragmentShader :: setFloat ( const char * name, float value )
{
    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return false;

    glUniform1fARB ( loc, value );

    return true;
}

bool    FragmentShader :: setFloat ( int loc, float value )
{
    glUniform1fARB ( loc, value );

    return true;
}

bool    FragmentShader :: setInt ( const char * name, int value )
{
    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return false;

    glUniform1iARB ( loc, value );

    return true;
}

bool    FragmentShader :: setInt ( int loc, int value )
{
    glUniform1iARB ( loc, value );

    return true;
}

bool    FragmentShader :: setMatrix  ( const char * name, const Matrix4x4& value )
{
    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return false;

    glUniformMatrix4fvARB ( loc, 1, GL_FALSE, value [0] );

    return true;
}

bool    FragmentShader :: setMatrix  ( const char * name, float value [16] )
{
    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return false;

    glUniformMatrix4fvARB ( loc, 1, GL_FALSE, value );

    return true;
}

bool    FragmentShader :: setMatrix  ( const char * name, const Matrix3D& value )
{
    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return false;

    glUniformMatrix3fvARB ( loc, 1, GL_FALSE, value [0] );

    return true;
}

int     FragmentShader :: locForUniformName ( const char * name )
{
    return glGetUniformLocationARB ( program, name );
}

Vector4D    FragmentShader :: getVector ( const char * name )
{
    float   values [4];

    int loc = glGetUniformLocationARB ( program, name );

    if ( loc < 0 )
        return Vector4D ( 0, 0, 0, 0 );

    glGetUniformfvARB ( program, loc, values );

    return Vector4D ( values [0], values [1], values [2], values [3] );
}





int     FragmentShader :: maxFragmentTextureUnits ()
{
    int maxFragmentTextureUnits;

    glGetIntegerv ( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &maxFragmentTextureUnits );

    return maxFragmentTextureUnits;
}



int     FragmentShader :: maxCombinedTextureUnits ()
{
    int maxCombinedTextureUnits;

    glGetIntegerv ( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &maxCombinedTextureUnits );

    return maxCombinedTextureUnits;
}

int     FragmentShader :: maxVaryingFloats ()
{
    int maxVaryingFloats;

    glGetIntegerv ( GL_MAX_VARYING_FLOATS_ARB, &maxVaryingFloats );


    return maxVaryingFloats;
}

int     FragmentShader :: maxFragmentUniformComponents ()
{
    int maxFragmentUniformComponents;

    glGetIntegerv ( GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &maxFragmentUniformComponents );

    return maxFragmentUniformComponents;
}

int     FragmentShader :: maxTextureCoords ()
{
    int maxTextureCoords;

    glGetIntegerv ( GL_MAX_TEXTURE_COORDS_ARB, &maxTextureCoords );

    return maxTextureCoords;
}

FragmentShader ::~FragmentShader()
{
	clear();
}